#include "public.h"
#include "lcd.h"
#include "temp.h"
#include "PWM.h"
#include "AD.h"
#include "key.h"

// 系统模式定义
#define MODE_AUTO    0    // 自动模式
#define MODE_MANUAL  1    // 手动模式
#define MODE_KEY     2    // 键盘控制模式

// 全局变量
static unsigned char g_system_mode = MODE_AUTO;    // 系统运行模式
static unsigned int g_temp_value;                  // 当前温度值
static unsigned char g_motor_speed;                // 电机速度(0-100)
static unsigned char g_temp_high = 60;             // 温度上限
static unsigned char g_temp_low = 20;              // 温度下限

/*******************************************************************************
* 函数名         : Number2String
* 功能描述       : 将数字转换为字符串
* 输入           : num - 要转换的数字, str - 存放结果的字符数组
* 输出           : 无
*******************************************************************************/
void Number2String(unsigned int num, char* str)
{
    char temp[6];
    unsigned char i = 0, j = 0;
    
    // 特殊处理0
    if(num == 0)
    {
        str[0] = '0';
        str[1] = '\0';
        return;
    }
    
    // 将数字转换为字符并逆序存储
    while(num)
    {
        temp[i++] = num % 10 + '0';
        num /= 10;
    }
    
    // 将逆序的数字复制回str，并反转顺序
    while(i > 0)
    {
        str[j++] = temp[--i];
    }
    str[j] = '\0';
}

/*******************************************************************************
* 函数名         : Display_Update
* 功能描述       : 更新LCD显示
*******************************************************************************/
void Display_Update(void)
{
    char temp_buf[16];
    char num_str[6];
    unsigned char i, len;
    
    // 第一行显示模式和温度
    switch(g_system_mode)
    {
        case MODE_AUTO:
            LCD_Dispstring(0, 0, "AUTO");
            break;
        case MODE_MANUAL:
            LCD_Dispstring(0, 0, "MANUAL");
            break;
        case MODE_KEY:
            LCD_Dispstring(0, 0, "KEY");
            break;
    }
    
    // 显示温度
    Number2String(g_temp_value/10, num_str);
    temp_buf[0] = 'T';
    temp_buf[1] = ':';
    // 计算整数部分长度
    for(len = 0; num_str[len] != '\0'; len++);
    // 复制整数部分
    for(i = 0; i < len; i++)
    {
        temp_buf[i+2] = num_str[i];
    }
    // 添加小数点和小数位
    temp_buf[len+2] = '.';
    temp_buf[len+3] = g_temp_value%10 + '0';
    temp_buf[len+4] = '\0';
    LCD_Dispstring(10, 0, temp_buf);
    
    // 第二行显示电机速度和温度范围
			temp_buf[0] = 'S';
			temp_buf[1] = 'P';
			temp_buf[2] = 'D';
			temp_buf[3] = ':';
			Number2String(g_motor_speed, num_str);
			for(i = 0; num_str[i] != '\0'; i++)
			{
					temp_buf[i+4] = num_str[i];
			}
			temp_buf[i+4] = '%';
			// 在%后面添加三个空格
			temp_buf[i+5] = ' ';
			temp_buf[i+6] = ' ';
			temp_buf[i+7] = ' ';
			Number2String(g_temp_low, num_str);
			temp_buf[i+8] = num_str[0];  // 索引从i+9开始
			temp_buf[i+9] = num_str[1];
			temp_buf[i+10] = '-';
			Number2String(g_temp_high, num_str);
			temp_buf[i+11] = num_str[0];
			temp_buf[i+12] = num_str[1];
			temp_buf[i+13] = 'C';
			temp_buf[i+14] = '\0';
			LCD_Dispstring(0, 1, temp_buf);

}


/*******************************************************************************
* 函数名         : Lcd_student
* 功能描述       : 显示学号
*******************************************************************************/
void LCD_student(void)
{
    
        LCD_Clear();            // 清空屏幕
        LCD_Dispstring(0, 0, "2310605112"); // 第一行显示学号
        LCD_Dispstring(0, 1, "System Init.....");
				delay_ms(1000);
}

/*******************************************************************************
* 函数名         : Auto_Control
* 功能描述       : 自动模式下的温度控制
*******************************************************************************/
void Auto_Control(void)
{
    // 温度超过上限，全速运转散热
    if(g_temp_value > g_temp_high * 10)
    {
        g_motor_speed = 100;
    }
    // 温度低于下限，停止运转
    else if(g_temp_value < g_temp_low * 10)
    {
        g_motor_speed = 0;
    }
    // 温度在范围内，按比例调节速度
    else
    {
        g_motor_speed = (g_temp_value - g_temp_low * 10) * 100 / 
                       ((g_temp_high - g_temp_low) * 10);
    }
    
    // 更新PWM输出
    PWM_SetDuty(g_motor_speed);
}

/*******************************************************************************
* 函数名         : Manual_Control
* 功能描述       : 手动模式下的速度控制
*******************************************************************************/
// 延时计数器
static unsigned char delay_count = 0;

void Manual_Control(void)
{
    unsigned int adc_value;
    unsigned long temp;
    static unsigned char last_speed = 0;
    
    // 每隔一定时间才更新一次速度值
    if(++delay_count < 5)  // 减少延时到约25ms更新一次
        return;
    delay_count = 0;
    
    // 读取电位器的ADC值（使用通道0）
    adc_value = ADC_Read(0);
    
    // 调整ADC值范围，确保能达到最大值
    // XPT2046的实际输出可能不会达到理论最大值4095
    // 根据实际测量，调整为最大值约为3000
    if(adc_value > 4000)
        adc_value = 4000;
    
    // 将ADC值(0-4000)转换为速度值(0-100)
    // 使用long类型避免溢出，并调整计算顺序
    temp = (unsigned long)adc_value * 100;
    g_motor_speed = (unsigned char)(temp / 4000);
    
    // 限制最小速度为0，最大速度为100
    if(g_motor_speed > 100)
        g_motor_speed = 100;
    
    // 添加变化阈值，减少小幅度抖动
    if((g_motor_speed > last_speed && g_motor_speed - last_speed < 2) ||
       (last_speed > g_motor_speed && last_speed - g_motor_speed < 2))
        g_motor_speed = last_speed;
    last_speed = g_motor_speed;
    
    // 更新PWM输出
    PWM_SetDuty(g_motor_speed);
}

/*******************************************************************************
* 函数名         : Key_Process
* 功能描述       : 按键处理
*******************************************************************************/
void Key_Process(void)
{
    unsigned char key = Key_Scan();
    
    switch(key)
    {
        case KEY_1:    // 模式切换
            if(g_system_mode < 2)
            {
                g_system_mode++;
            }
            else
            {
                g_system_mode = MODE_AUTO;
            }
            LCD_Clear();
            break;
            
        case KEY_2:    // 增加温度阈值或速度
            if(g_system_mode == MODE_AUTO)
            {
                if(g_temp_high < 80)
                {
                    g_temp_high++;
                    if(g_temp_high <= g_temp_low)  // 确保上限大于下限
                        g_temp_high = g_temp_low + 1;
                }
            }
            break;
            
        case KEY_3:    // 减少温度阈值
            if(g_system_mode == MODE_AUTO)
            {
                if(g_temp_low > 0)
                {
                    g_temp_low--;
                    if(g_temp_low >= g_temp_high)  // 确保下限小于上限
                        g_temp_low = g_temp_high - 1;
                }
            }
            break;

        case KEY_4:    // 按键控制加速（键盘控制模式）
            if(g_system_mode == MODE_KEY)
            {
                if(g_motor_speed <= 100)  // 限制最大速度为100%
                {
                    g_motor_speed += 10;  // 以10%为步进增加速度
                }
                else
                {
                    g_motor_speed = 100;
                }
                PWM_SetDuty(g_motor_speed);  // 更新PWM输出
            }
            break;

        case KEY_5:    // 按键控制减速（键盘控制模式）
            if(g_system_mode == MODE_KEY)
            {
                if(g_motor_speed >= 10)  // 确保不会减到负值
                {
                    g_motor_speed -= 10;  // 以10%为步进减少速度
                }
                else
                {
                    g_motor_speed = 0;
                }
                PWM_SetDuty(g_motor_speed);  // 更新PWM输出
            }
            break;
    }
}

/*******************************************************************************
* 函数名         : System_Init
* 功能描述       : 系统初始化
*******************************************************************************/
void System_Init(void)
{
    // 初始化LCD
    LCD_Init();
    
    // 初始化PWM
    PWM_Init();
    
    // 初始化ADC
    ADC_Init();
    
    // 初始化按键
    Key_Init();
    
    // 初始显示
    LCD_Clear();
		LCD_student();
    LCD_Clear();
    Display_Update();
}

/*******************************************************************************
* 函数名         : main
* 功能描述       : 主函数
*******************************************************************************/
void main(void)
{
    unsigned char temp_count = 0;
    unsigned char display_count = 0;
    
    // 系统初始化
    System_Init();
		
    while(1)
    {
        // 温度读取（每250ms读取一次）
        if(++temp_count >= 50)
        {
            temp_count = 0;
            g_temp_value = Ds18b20ReadTemp();
        }
        
        // 按键处理
        Key_Process();
        
        // 根据模式执行相应的控制
        if(g_system_mode == MODE_AUTO)
        {
            Auto_Control();
        }
        else if(g_system_mode == MODE_MANUAL)
        {
            Manual_Control();
        }
        else if(g_system_mode == MODE_KEY)
        {
            // 键盘控制模式下速度由KEY4和KEY5在KEY_PROS直接控制
        }
        
        // 显示更新（每100ms更新一次）
        if(++display_count >= 20)
        {
            display_count = 0;
            Display_Update();
        }
        
        // 减少主循环延时以提高响应性
        delay_ms(5);
    }
}